package org.zxl.iotest.netty.test1;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.FixedLengthFrameDecoder;
import io.netty.handler.codec.json.JsonObjectDecoder;
import io.netty.handler.timeout.IdleStateHandler;

import java.util.concurrent.TimeUnit;

public class Server {
    public static void main(String[] args) throws Exception {
        // 1 创建线两个事件循环组线程池。默认线程池大小为1
        // 一个是用于处理服务器端接收客户端连接的; Accetpt 连接建立事件并分发请求
        // 一个是进行网络通信的（网络读写的）;处理 I/O 读写事件和业务逻辑。
        EventLoopGroup boosGroup = new NioEventLoopGroup();
        EventLoopGroup workGroup = new NioEventLoopGroup();

        // 2 创建辅助工具类ServerBootstrap，用于服务器通道的一系列配置
        ServerBootstrap b = new ServerBootstrap();
        b.group(boosGroup, workGroup) // 绑定俩个线程组
                .channel(NioServerSocketChannel.class) // 指定NIO的模式.NioServerSocketChannel对应TCP, NioDatagramChannel对应UDP
//                .option(ChannelOption.SO_BACKLOG, 1024) // 设置TCP缓冲区
//                .option(ChannelOption.SO_SNDBUF, 32 * 1024) // 设置发送缓冲大小
//                .option(ChannelOption.SO_RCVBUF, 32 * 1024) // 这是接收缓冲大小
                .option(ChannelOption.SO_KEEPALIVE, true) // 保持连接
                .childHandler(new ChannelInitializer<SocketChannel>() {
                    @Override
                    protected void initChannel(SocketChannel sc) throws Exception {  //SocketChannel建立连接后的管道
                        // 3 在这里配置 通信数据的处理逻辑, 可以addLast多个...
                        sc.pipeline()
//                                .addLast(new IdleStateHandler(3,5,7, TimeUnit.SECONDS))
//                                .addLast(new MyServerIdleHandler()) //心跳
//                                .addLast(new FixedLengthFrameDecoder(4)) //定长解码器
                                .addLast(new JsonObjectDecoder()) //json解码器
                                .addLast(new ServerInboundHandler())
                                .addLast(new ServerInboundHandler2())
                                .addLast(new ServerOutboundHandler())
                                .addLast(new ServerOutboundHandler2())
                        ;
                    }
                });

        // 4 绑定端口, bind返回future(异步), 加上sync阻塞在获取连接处
        ChannelFuture cf1 = b.bind(8765).sync();
        //ChannelFuture cf2 = b.bind(8764).sync();   //可以绑定多个端口
        // 5 等待关闭, 加上sync阻塞在关闭请求处
        cf1.channel().closeFuture().sync();
        //cf2.channel().closeFuture().sync();
        boosGroup.shutdownGracefully();
        workGroup.shutdownGracefully();
    }
}
